Climate Aid → Pollution — ADM2 Staggered DiD Exploration

EDGAR × GODAD — ADM2-level treatment (first project) & pollution outcomes

Author

Pierre Beaucoral

Published

October 9, 2025

Show code
suppressPackageStartupMessages({
  library(data.table); library(dplyr); library(tidyr)
  library(readr); library(arrow); library(sf)
  library(stringr); library(janitor)
  library(ggplot2); library(scales)
  # DiD
  library(did)            # Callaway & Sant'Anna
  library(fixest)         # sunab() if you also want SA later
})

options(datatable.print.nrows = 50)
setDTthreads(percent = 100)

bt <- function(b, se = NULL) {
  pct <- (exp(b) - 1) * 100
  if (is.null(se)) return(pct)
  c(
    pct = pct,
    lo  = (exp(b - 1.96 * se) - 1) * 100,
    hi  = (exp(b + 1.96 * se) - 1) * 100
  )
}
Show code
params <- list(
  adm2_shp  = '/Users/pierrebeaucoral/Documents/Pro/Thèse CERDI/Recherche/GODAD/Data/GADM/gadm_410-levels_ADM_2.shp',
  edgar_cache_file = "/Users/pierrebeaucoral/Documents/Pro/Thèse CERDI/Recherche/GODAD/Data/Cache/edgar_adm2_panel.rds",
  edgar_years = 1997:2023,
  edgar_var = "CO2",
  godad_file = '/Users/pierrebeaucoral/Documents/Pro/Thèse CERDI/Recherche/GODAD/Data/climate_finance_total.csv',
  godad_gid2_col = 'gid_2',
  godad_year = 'startyear',
  crs_target = 4326
)

1 Aim & design

We create an ADM2-year panel to study the effect of climate aid arrival on pollution outcomes from EDGAR. Treatment is defined as first year a climate project occurs in an ADM2 (staggered adoption). Outcome is the ADM2-area-weighted pollution mean.

2 Paths, helpers, and ADM2 layer

Show code
adm2 <- st_read(params$adm2_shp, quiet = TRUE) |> st_transform(params$crs_target)
nm <- names(adm2)
gid2_col  <- nm[str_detect(nm, "(?i)^GID_?2$|gid_?2|code_?2|adm2_id")][1]
name_col  <- nm[str_detect(nm, "(?i)^NAME_?2$|name_?2|adm2|district|county|province")][1]
if (is.na(gid2_col)) stop("Could not detect ADM2 code column in shapefile.")
if (is.na(name_col)) name_col <- gid2_col

adm2_key <- adm2 |>
  st_drop_geometry() |>
  transmute(adm2_id = .data[[gid2_col]],
            adm2_name = as.character(.data[[name_col]])) |>
  as.data.table()

3 EDGAR outcomes → ADM2-year

The code below recursively loads EDGAR data

Show code
stopifnot(file.exists(params$edgar_cache_file))
edgar_dt <- readRDS(params$edgar_cache_file) |> as.data.table()

# Expect columns: year, GID, co2_tonnes (from your glimpse)
edgar_dt[, year := as.integer(year)]
edgar_dt <- edgar_dt[year %in% params$edgar_years]

edgar_dt <- edgar_dt[, .(
  adm2_id = as.character(GID),
  year    = year,
  pollution_CO2 = as.numeric(co2_tonnes)
)]

# average duplicates if any
edgar_dt <- edgar_dt[, .(pollution_CO2 = mean(pollution_CO2, na.rm = TRUE)),
                     by = .(adm2_id, year)]

# Winsorized and log outcome
wfun <- function(x, p = 0.01) {
  ql <- quantile(x, p, na.rm = TRUE); qh <- quantile(x, 1-p, na.rm = TRUE)
  pmin(pmax(x, ql), qh)
}
edgar_dt[, pollution_CO2_w   := wfun(pollution_CO2)]
edgar_dt[, pollution_CO2_log := log1p(pollution_CO2)]

# base panel skeleton from EDGAR (ids present in outcomes)
ids   <- sort(unique(edgar_dt$adm2_id))
years <- sort(unique(edgar_dt$year))
base_panel <- CJ(adm2_id = ids, year = years)[edgar_dt, on = .(adm2_id, year)]
base_panel <- merge(base_panel, adm2_key, by = "adm2_id", all.x = TRUE)

3.1 Quick sanity

Show code
read_any <- function(path) {
  ext <- tolower(tools::file_ext(path))
  switch(ext,
         csv = readr::read_csv(path, show_col_types = FALSE),
         rds = readRDS(path),
         parquet = arrow::read_parquet(path),
         fst = fst::read_fst(path) |> as.data.frame(),
         stop("Unsupported GODAD format: ", ext))
}

godad <- read_any(params$godad_file) |> janitor::clean_names() |> as.data.table()
stopifnot(all(c(params$godad_gid2_col, params$godad_year) %in% names(godad)))

godad <-godad%>%
  filter(startyear>=1997)

godad[, adm2_id := as.character(get(params$godad_gid2_col))]
godad[, year    := suppressWarnings(as.integer(get(params$godad_year)))]
godad <- godad[!is.na(adm2_id) & !is.na(year)]

# Flags from your schema
stopifnot(all(c("climate_relevance","meta_category") %in% names(godad)))
godad[, climate_relevance := as.integer(climate_relevance)]
godad[, meta_category := tolower(trimws(meta_category))]

godad[, is_climate     := climate_relevance == 1L]
godad[, is_nonclimate  := climate_relevance == 0L]
godad[, is_mitigation  := str_detect(meta_category, "\\bmitig")]     # robust
godad[, is_adaptation  := str_detect(meta_category, "\\badapt")]     # robust

# helper: first adoption year by ADM2
first_adopt <- function(dt_subset) {
  if (nrow(dt_subset) == 0L) return(data.table(adm2_id = character(), g = integer()))
  out <- dt_subset[, .(g = suppressWarnings(min(as.integer(year), na.rm = TRUE))), by = adm2_id]
  out[is.infinite(g), g := NA_integer_][]
}

adopt_adapt      <- first_adopt(godad[is_adaptation == TRUE])
adopt_mitig      <- first_adopt(godad[is_mitigation == TRUE])
adopt_climate    <- first_adopt(godad[is_climate == TRUE])
adopt_nonclimate <- first_adopt(godad[is_nonclimate == TRUE])

sapply(list(adapt = adopt_adapt, mitig = adopt_mitig, climate = adopt_climate, nonclimate = adopt_nonclimate), nrow)
     adapt      mitig    climate nonclimate 
      2166       2137       5864      16374 
Show code
yvar <- if ("pollution_CO2_log" %in% names(base_panel)) "pollution_CO2_log" else "pollution_CO2_w"

run_csdid <- function(base_panel, adopt_tbl, label, min_e = -10, max_e = 20) {
  P <- merge(base_panel[, .(adm2_id, year, y = get(yvar))],
             adopt_tbl, by = "adm2_id", all.x = TRUE)

  # Treated flags & event time
  P[, treated  := as.integer(!is.na(g) & year >= g)]
  P[, rel_time := ifelse(is.na(g), NA_integer_, year - g)]
  P[, adm2_id_int := as.integer(factor(adm2_id))]

  # Drop missing outcome and units treated in first overall year
  min_year <- min(P$year, na.rm = TRUE)
  D <- P[!is.na(y) & (is.na(g) | g > min_year)]

  if (nrow(D[!is.na(g)]) == 0L) {
    warning(sprintf("No treated units for %s — skipping.", label))
    return(NULL)
  }

  att <- did::att_gt(
    yname   = "y",
    tname   = "year",
    idname  = "adm2_id_int",
    gname   = "g",
    data    = D,
    panel   = TRUE,                 # repeated cross-sections at ADM2-year
    control_group = "notyettreated",
    allow_unbalanced_panel = TRUE
  )

  list(
    label = label,
    att   = att,
    es    = did::aggte(att, type = "dynamic", min_e = min_e, max_e = max_e),
    grp   = did::aggte(att, type = "group")
  )
}

4 CS DiD

We identify the first year in which an ADM2 receives at least one climate project. If the GODAD file already has an ADM2 code, we use it; if not, we perform a spatial join using the point geometry.

Show code
res_adapt <- run_csdid(base_panel, adopt_adapt,      "Adaptation")
res_mitig <- run_csdid(base_panel, adopt_mitig,      "Mitigation")
res_clim  <- run_csdid(base_panel, adopt_climate,    "All climate")
res_noncl <- run_csdid(base_panel, adopt_nonclimate, "Non-climate")

5 CS DiD Plot

Show code
make_es_df <- function(res) {
  if (is.null(res)) return(NULL)
  es <- res$es
  data.frame(label = res$label, egt = es$egt, att = es$att.egt, se = es$se.egt)
}

es_all <- rbind(
  make_es_df(res_adapt),
  make_es_df(res_mitig),
  make_es_df(res_clim),
  make_es_df(res_noncl)
)

if (!is.null(es_all)) {
  ggplot(es_all, aes(egt, att)) +
    geom_hline(yintercept = 0, linetype = 2) +
    geom_point() +
    geom_errorbar(aes(ymin = att - 1.96*se, ymax = att + 1.96*se), width = 0.15) +
    geom_vline(xintercept = -1, linetype = 2) +
    facet_wrap(~ label, ncol = 2, scales = "free_y") +
    labs(title = sprintf("Dynamic ATT (y = %s)", yvar),
         x = "Event time (t - g)", y = "ATT") +
    theme_minimal(base_size = 12)
}

Show code
summ_line <- function(res) {
  if (is.null(res)) return(NULL)
  s <- capture.output(print(summary(res$grp)))
  data.frame(model = res$label, summary = paste(s, collapse = "\n"))
}

summ_all <- dplyr::bind_rows(
  summ_line(res_adapt),
  summ_line(res_mitig),
  summ_line(res_clim),
  summ_line(res_noncl)
)

if (nrow(summ_all)) {
  cat("\n\n===== Overall ATT (group aggregated) =====\n")
  for (i in seq_len(nrow(summ_all))) {
    cat("\n--", summ_all$model[i], "--\n", summ_all$summary[i], "\n")
  }
}


===== Overall ATT (group aggregated) =====

-- Adaptation --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
     ATT    Std. Error     [ 95%  Conf. Int.] 
 -0.0078        0.0098    -0.0269      0.0113 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band]  
  2001   0.0523     0.0529       -0.0942      0.1989  
  2002   0.0070     0.0613       -0.1630      0.1769  
  2003  -0.0060     0.0353       -0.1037      0.0917  
  2004  -0.1699     0.0681       -0.3586      0.0187  
  2005  -0.0958     0.0252       -0.1657     -0.0260 *
  2006   0.0257     0.0513       -0.1165      0.1678  
  2007   0.0101     0.0824       -0.2180      0.2383  
  2008  -0.0822     0.0830       -0.3120      0.1476  
  2009  -0.0482     0.0361       -0.1482      0.0517  
  2010  -0.0878     0.0360       -0.1875      0.0120  
  2011   0.0165     0.0346       -0.0794      0.1125  
  2012   0.0097     0.0206       -0.0473      0.0667  
  2013   0.0184     0.0659       -0.1641      0.2009  
  2014   0.0310     0.0216       -0.0287      0.0907  
  2015   0.0235     0.0265       -0.0499      0.0969  
  2016  -0.0015     0.0211       -0.0601      0.0570  
  2017   0.0072     0.0169       -0.0396      0.0539  
  2018   0.0008     0.0132       -0.0357      0.0373  
  2019  -0.0168     0.0192       -0.0700      0.0364  
  2020  -0.0668     0.0177       -0.1157     -0.0179 *
  2021   0.0367     0.0159       -0.0073      0.0806  
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 

-- Mitigation --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
     ATT    Std. Error     [ 95%  Conf. Int.] 
 -0.0012         0.015    -0.0306      0.0282 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band] 
  2001   0.0517     0.1185       -8.5765      8.6798 
  2002   0.1522     0.0438       -3.0329      3.3374 
  2003   0.1966     0.0580       -4.0252      4.4184 
  2004  -0.0124     0.0785       -5.7299      5.7052 
  2005  -0.0122     0.0695       -5.0717      5.0473 
  2006   0.0726     0.0792       -5.6920      5.8372 
  2007   0.0363     0.0780       -5.6432      5.7158 
  2008   0.0859     0.0736       -5.2708      5.4425 
  2009  -0.0867     0.0350       -2.6314      2.4579 
  2010   0.0621     0.0575       -4.1205      4.2446 
  2011  -0.0540     0.0336       -2.4992      2.3912 
  2012  -0.0311     0.0285       -2.1054      2.0432 
  2013  -0.0318     0.0311       -2.2934      2.2298 
  2014  -0.0391     0.0265       -1.9660      1.8879 
  2015   0.0552     0.0340       -2.4173      2.5277 
  2016  -0.0103     0.0217       -1.5935      1.5730 
  2017  -0.0178     0.0277       -2.0351      1.9994 
  2018  -0.0192     0.0333       -2.4446      2.4063 
  2019  -0.0342     0.0228       -1.6952      1.6268 
  2020   0.0134     0.0282       -2.0374      2.0641 
  2021  -0.0201     0.0299       -2.1999      2.1597 
  2022   0.0636     0.0061       -0.3777      0.5049 
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 

-- All climate --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
     ATT    Std. Error     [ 95%  Conf. Int.] 
 -0.0888        0.0654     -0.217      0.0395 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band] 
  2001  -0.0115     0.0618       -0.4138      0.3908 
  2002   0.0971     0.0592       -0.2883      0.4825 
  2003   0.0141     0.0581       -0.3640      0.3922 
  2004  -0.1467     0.0678       -0.5880      0.2947 
  2005  -0.0895     0.0666       -0.5230      0.3441 
  2006  -0.0593     0.0632       -0.4706      0.3521 
  2007  -0.1764     0.0659       -0.6051      0.2523 
  2008  -0.1002     0.0728       -0.5739      0.3735 
  2009  -0.0955     0.0776       -0.6002      0.4092 
  2010  -0.0560     0.0644       -0.4751      0.3631 
  2011  -0.0905     0.0577       -0.4657      0.2846 
  2012  -0.0857     0.0658       -0.5140      0.3426 
  2013  -0.0985     0.0738       -0.5784      0.3814 
  2014  -0.1233     0.0432       -0.4045      0.1579 
  2015  -0.0555     0.0648       -0.4774      0.3664 
  2016  -0.0750     0.0929       -0.6792      0.5292 
  2017  -0.0911     0.0618       -0.4931      0.3108 
  2018  -0.0793     0.0355       -0.3100      0.1514 
  2019  -0.1661     0.0393       -0.4215      0.0893 
  2020  -0.1796     0.0468       -0.4840      0.1248 
  2021  -0.1627     0.1405       -1.0770      0.7516 
  2022   0.0188     0.0092       -0.0410      0.0786 
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 

-- Non-climate --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
   ATT    Std. Error     [ 95%  Conf. Int.] 
 0.014        0.0112    -0.0079       0.036 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band]  
  2001   0.0065     0.0185       -0.0470      0.0600  
  2002   0.0247     0.0198       -0.0323      0.0817  
  2003   0.0325     0.0238       -0.0362      0.1012  
  2004   0.0138     0.0156       -0.0313      0.0589  
  2005  -0.0538     0.0191       -0.1089      0.0013  
  2006   0.0806     0.0176        0.0298      0.1314 *
  2007  -0.0444     0.0194       -0.1003      0.0116  
  2008   0.0522     0.0180        0.0004      0.1040 *
  2009  -0.0300     0.0238       -0.0987      0.0388  
  2010   0.0186     0.0197       -0.0382      0.0755  
  2011  -0.0009     0.0266       -0.0775      0.0757  
  2012   0.0042     0.0234       -0.0633      0.0717  
  2013   0.0195     0.0193       -0.0363      0.0753  
  2014  -0.0024     0.0211       -0.0632      0.0584  
  2015   0.0074     0.0191       -0.0476      0.0625  
  2016   0.0089     0.0167       -0.0392      0.0570  
  2017   0.0256     0.0182       -0.0270      0.0782  
  2018   0.0311     0.0301       -0.0558      0.1180  
  2019  -0.0190     0.0181       -0.0714      0.0333  
  2020  -0.0227     0.0192       -0.0780      0.0326  
  2021  -0.0109     0.0341       -0.1093      0.0876  
  2022   0.0459     0.0154        0.0015      0.0904 *
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 
Show code
# SAFE overall row from a result object
summ_line_overall <- function(res, use_fallback = TRUE) {
  if (is.null(res) || is.null(res$grp)) return(NULL)

  # Prefer group overall directly without calling summary() (avoids noisy prints)
  att <- tryCatch(res$grp$overall.att, error = function(e) NA_real_)
  se  <- tryCatch(res$grp$overall.se,  error = function(e) NA_real_)

  if (length(att) == 1L && is.finite(att) && length(se) == 1L && is.finite(se)) {
    return(data.frame(label = res$label, att = att, se = se))
  }

  # Optional fallback: inverse-variance weighted mean of post dynamic ATTs
  if (use_fallback && !is.null(res$es) && length(res$es$att.egt)) {
    df <- data.frame(att = res$es$att.egt, se = res$es$se.egt, e = res$es$egt)
    df <- df[is.finite(df$att) & is.finite(df$se) & df$e >= 0, ]
    if (nrow(df) >= 1 && all(df$se > 0)) {
      w   <- 1 / (df$se^2)
      att <- sum(w * df$att) / sum(w)
      se  <- sqrt(1 / sum(w))
      return(data.frame(label = res$label, att = att, se = se))
    }
  }

  # Nothing usable for this spec
  NULL
}


summ_all <- dplyr::bind_rows(
  summ_line_overall(res_adapt), summ_line_overall(res_mitig),
  summ_line_overall(res_clim),  summ_line_overall(res_noncl)
) |>
  dplyr::mutate(
    pct = bt(att),
    lo  = bt(att, se)["lo"], hi = bt(att, se)["hi"]
  )

gt::gt(summ_all) |>
  gt::fmt_number(columns = c(pct, lo, hi), decimals = 1) |>
  gt::cols_label(pct="ATT (%)", lo="95% lo", hi="95% hi") |>
  gt::tab_caption("Overall ATT (group aggregated), back-transformed to %.")
Overall ATT (group aggregated), back-transformed to %.
label att se ATT (%) 95% lo 95% hi
Adaptation -0.007793955 0.009752258 −0.8 NA NA
Mitigation -0.001203225 0.015000690 −0.1 NA NA
All climate -0.088767206 0.065429463 −8.5 NA NA
Non-climate 0.014032414 0.011198641 1.4 NA NA

5.1 Intensity

Show code
suppressPackageStartupMessages({
  library(data.table); library(ggplot2); library(did)
})

setDT(godad); setDT(base_panel)

# Prefer per-location split columns if already computed in `godad`
amt_cols_priority <- c("disb_loc_evensplit", "comm_loc_evensplit",
                       "disb_amount", "commit_amount", "amount")

amount_col_godad <- amt_cols_priority[amt_cols_priority %in% names(godad)][1]
stopifnot(length(amount_col_godad) == 1)

message("Using amount column from godad: ", amount_col_godad)

# Sanity: we need ADM2 id and YEAR in godad; if year is a date, coerce to integer
if (!"year" %in% names(godad)) {
  stop("`godad` must have a `year` column (integer).")
}
if (!"adm2_id" %in% names(godad)) {
  stop("`godad` must carry `adm2_id` (or do the spatial join before this step).")
}


# Helper to build ADM2-year totals for a filter
adm2yr_sum <- function(gd, keep_expr) {
  x <- gd[eval(keep_expr),
          .(amt = sum(get(amount_col_godad), na.rm = TRUE)),
          by = .(adm2_id, year)]
  setnames(x, "amt", "dose_amt")
  x[]
}

# Category filters (adjust if your flags differ)
gd <- copy(godad)

has_cols <- names(gd)
req_flags <- c("is_adaptation","is_mitigation","is_climate")
if (!all(req_flags %in% has_cols)) {
  stop("godad must have logical flags: is_adaptation, is_mitigation, is_climate.")
}

adm2yr_adapt      <- adm2yr_sum(gd, quote(is_adaptation == TRUE))
adm2yr_mitig      <- adm2yr_sum(gd, quote(is_mitigation == TRUE))
adm2yr_climate    <- adm2yr_sum(gd, quote(is_climate     == TRUE))
adm2yr_nonclimate <- adm2yr_sum(gd, quote(is_climate     == FALSE))

# Generic merge + first adoption helper
attach_dose_and_adopt <- function(bp, adm2yr) {
  dt <- adm2yr[bp, on = c("adm2_id","year")]
  dt[is.na(dose_amt), dose_amt := 0]                # zero when no project that year
  # First year with positive amount is the adoption g
  gtab <- dt[dose_amt > 0, .(g = min(year)), by = adm2_id]
  dt <- gtab[dt, on = "adm2_id"]
  dt[]
}

bp_adapt      <- attach_dose_and_adopt(base_panel, adm2yr_adapt)
bp_mitig      <- attach_dose_and_adopt(base_panel, adm2yr_mitig)
bp_climate    <- attach_dose_and_adopt(base_panel, adm2yr_climate)
bp_nonclimate <- attach_dose_and_adopt(base_panel, adm2yr_nonclimate)


post_totals_and_bins <- function(dt, n_bins = 4) {
  d <- copy(dt)
  setorder(d, adm2_id, year)
  # cumulative dose (for convenience)
  d[, dose_cum := cumsum(dose_amt), by = adm2_id]
  # total post-treatment dose per unit (from g onward)
  posttab <- d[!is.na(g), .(post_total = max(dose_cum[year >= g[1L]], na.rm = TRUE)), by = adm2_id]
  d <- posttab[d, on = "adm2_id"]

  # Cut bins on treated units only
  treated <- d[!is.na(g), unique(adm2_id)]
  x <- d[adm2_id %in% treated, post_total]
  # robust breaks
  mk_breaks <- function(x, n_bins = 4) {
    if (length(unique(na.omit(x))) < n_bins) x <- x + rnorm(length(x), sd = sd(x, na.rm=TRUE)*1e-8)
    b <- quantile(x, probs = seq(0,1,length.out = n_bins+1), na.rm = TRUE, type = 1) |> unique() |> sort()
    if (length(b) <= 2) b <- quantile(x, probs = c(0,.5,1), na.rm = TRUE, type = 1) |> unique() |> sort()
    b
  }
  brks <- mk_breaks(x, n_bins)
  d[, post_bin := cut(post_total, breaks = brks, include.lowest = TRUE, right = TRUE)]
  d[, post_bin := droplevels(post_bin)]
  d[]
}

bp_adapt      <- post_totals_and_bins(bp_adapt,      n_bins = 4)
bp_mitig      <- post_totals_and_bins(bp_mitig,      n_bins = 4)
bp_climate    <- post_totals_and_bins(bp_climate,    n_bins = 4)
bp_nonclimate <- post_totals_and_bins(bp_nonclimate, n_bins = 4)

Pre-treatment exposure per ADM2 (constant over time)

Show code
yvar <- "pollution_CO2_log"; stopifnot(yvar %in% names(base_panel))


suppressPackageStartupMessages({ library(data.table); library(did) })

check_and_fix_postdose <- function(dtf, yvar) {
  d <- as.data.table(copy(dtf))

  # 1) Outcome present?
  if (!yvar %in% names(d)) stop("Outcome column `", yvar, "` not found in data.")

  # 2) Year must be integer
  if (!is.integer(d$year)) {
    d[, year := as.integer(year)]
    if (anyNA(d$year)) stop("`year` coercion produced NAs — check your year values.")
  }

  # 3) ID should be numeric for did stability
  if (!is.numeric(d$adm2_id)) {
    d[, adm2_id_int := as.integer(factor(adm2_id))]
  } else {
    setnames(d, "adm2_id", "adm2_id_int")
  }

  # 4) Event-time origin g (first treat year) must exist for treated
  if (!"g" %in% names(d)) stop("`g` (first treatment year) is missing.")
  if (all(is.na(d$g))) warning("All g are NA — this category may have no treated units.")

  # 5) post_bin must exist and have levels with treated obs
  if (!"post_bin" %in% names(d)) stop("`post_bin` is missing. Run the bin construction step first.")
  d[, post_bin := droplevels(post_bin)]
  if (nlevels(d$post_bin) == 0L) stop("All `post_bin` are NA — no treated ADM2s or post_total is missing.")
  # Keep only bins that actually contain treated units
  has_tr <- d[, any(!is.na(g)), by = post_bin]
  valid_bins <- has_tr[ V1 == TRUE, post_bin ]
  d <- d[post_bin %in% valid_bins]
  d[, post_bin := droplevels(post_bin)]

  # 6) Drop rows with missing outcome
  d <- d[!is.na(get(yvar))]

  # 7) Basic summary to the console
  print(d[, .(n_rows=.N,
              n_adm2=uniqueN(adm2_id_int),
              n_treated=uniqueN(adm2_id_int[!is.na(g)]),
              bins=nlevels(post_bin))])
  print(d[, .(n_adm2=uniqueN(adm2_id_int),
              n_treated=uniqueN(adm2_id_int[!is.na(g)])),
          by=post_bin][order(post_bin)])

  return(d[])
}

# Wrapper to run CS-DiD with the numeric id we just ensured
run_postdose_csdid_safe <- function(dtf, label, yvar, min_e=-10, max_e=20) {
  dd <- check_and_fix_postdose(dtf, yvar)

  out_es <- vector("list", length(levels(dd$post_bin)))
  names(out_es) <- levels(dd$post_bin)

  for (b in levels(dd$post_bin)) {
    sub <- dd[post_bin == b]
    if (sub[!is.na(g), .N] == 0L) next

    att <- did::att_gt(
      yname   = yvar,
      tname   = "year",
      idname  = "adm2_id_int",   # <- numeric id
      gname   = "g",
      data    = sub,
      panel   = TRUE,
      control_group = "notyettreated",
      bstrap  = TRUE,
      clustervars = "adm2_id_int"
    )

    es <- did::aggte(att, type = "dynamic", min_e = min_e, max_e = max_e, na.rm = T)
    out_es[[b]] <- es
  }

  es_df <- data.table::rbindlist(lapply(names(out_es), function(b){
    x <- out_es[[b]]; if (is.null(x)) return(NULL)
    data.table(bin=b, e=x$egt, att=x$att.egt, se=x$se.egt)
  }), use.names=TRUE, fill=TRUE)
  
  bin_order <- dd[, .(ord = median(post_total, na.rm = TRUE)), by = post_bin][order(ord), as.character(post_bin)]
  es_df[, bin := factor(bin, levels = bin_order, ordered = TRUE)]             # <<<
  dd[,  post_bin := factor(post_bin, levels = bin_order, ordered = TRUE)]     # <<< (keeps summaries consistent)

  if (nrow(es_df)) {
    library(ggplot2)
    print(
      ggplot(es_df, aes(e, att, ymin=att-1.96*se, ymax=att+1.96*se)) +
        geom_hline(yintercept=0, linetype=2) +
        geom_ribbon(alpha=.15) +
        geom_line() +
        facet_wrap(~ bin, scales="free_y") +
        labs(x="Event time (years since first project)",
             y="ATT on outcome",
             title=paste("CS-DiD dynamics by post-treatment dose —", label)) +
        theme_minimal()
    )
  }

  invisible(list(es=out_es, df=es_df))
}



# Run all four families
res_adapt      <- run_postdose_csdid_safe(bp_adapt,      "Adaptation",  yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1:  35397   1539      1539     4
              post_bin n_adm2 n_treated
                <fctr>  <int>     <int>
1:     [18.5,1.39e+05]    387       387
2: (1.39e+05,8.39e+05]    383       383
3: (8.39e+05,3.25e+06]    385       385
4: (3.25e+06,6.35e+08]    384       384

Event-study by post-treatment total dose — stratified bins (treated-only cuts).

Event-study by post-treatment total dose — stratified bins (treated-only cuts).
Show code
res_mitig      <- run_postdose_csdid_safe(bp_mitig,      "Mitigation",  yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1:  34385   1495      1495     4
              post_bin n_adm2 n_treated
                <fctr>  <int>     <int>
1:      [266,9.01e+04]    374       374
2: (9.01e+04,1.12e+06]    374       374
3: (1.12e+06,4.81e+06]    374       374
4: (4.81e+06,9.82e+08]    373       373

Event-study by post-treatment total dose — stratified bins (treated-only cuts).

Event-study by post-treatment total dose — stratified bins (treated-only cuts).
Show code
res_climate    <- run_postdose_csdid_safe(bp_climate,    "All climate", yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1:  97359   4233      4233     4
             post_bin n_adm2 n_treated
               <fctr>  <int>     <int>
1:    [18.5,1.18e+05]   1059      1059
2: (1.18e+05,9.2e+05]   1058      1058
3: (9.2e+05,4.71e+06]   1058      1058
4: (4.71e+06,2.3e+09]   1058      1058

Event-study by post-treatment total dose — stratified bins (treated-only cuts).

Event-study by post-treatment total dose — stratified bins (treated-only cuts).
Show code
res_nonclimate <- run_postdose_csdid_safe(bp_nonclimate, "Non-climate", yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1: 267076  11612     11612     4
               post_bin n_adm2 n_treated
                 <fctr>  <int>     <int>
1: [-1.24e+03,9.21e+05]   2903      2903
2:  (9.21e+05,4.11e+06]   2916      2916
3:  (4.11e+06,1.73e+07]   2890      2890
4:  (1.73e+07,7.57e+09]   2903      2903

Event-study by post-treatment total dose — stratified bins (treated-only cuts).

Event-study by post-treatment total dose — stratified bins (treated-only cuts).

5.2 Excluding China

Show code
adopt_adapt <- adopt_adapt[!grepl("CHN", adm2_id), ]
adopt_mitig <- adopt_mitig[!grepl("CHN", adm2_id), ]
adopt_climate <- adopt_climate[!grepl("CHN", adm2_id), ]
adopt_nonclimate <- adopt_nonclimate[!grepl("CHN", adm2_id), ]


res_adapt_china <- run_csdid(base_panel, adopt_adapt,      "Adaptation")
res_mitig_china <- run_csdid(base_panel, adopt_mitig,      "Mitigation")
res_clim_china  <- run_csdid(base_panel, adopt_climate,    "All climate")
res_noncl_china <- run_csdid(base_panel, adopt_nonclimate, "Non-climate")


es_all_china <- rbind(
  make_es_df(res_adapt_china),
  make_es_df(res_mitig_china),
  make_es_df(res_clim_china),
  make_es_df(res_noncl_china)
)

if (!is.null(es_all_china)) {
  ggplot(es_all_china, aes(egt, att)) +
    geom_hline(yintercept = 0, linetype = 2) +
    geom_point() +
    geom_errorbar(aes(ymin = att - 1.96*se, ymax = att + 1.96*se), width = 0.15) +
    geom_vline(xintercept = -1, linetype = 2) +
    facet_wrap(~ label, ncol = 2, scales = "free_y") +
    labs(title = sprintf("Dynamic ATT (y = %s)", yvar),
         x = "Event time (t - g)", y = "ATT") +
    theme_minimal(base_size = 12)
}

Show code
summ_all_china <- dplyr::bind_rows(
  summ_line(res_adapt_china),
  summ_line(res_mitig_china),
  summ_line(res_clim_china),
  summ_line(res_noncl_china)
)

if (nrow(summ_all)) {
  cat("\n\n===== Overall ATT (group aggregated) =====\n")
  for (i in seq_len(nrow(summ_all_china))) {
    cat("\n--", summ_all_china$model[i], "--\n", summ_all_china$summary[i], "\n")
  }
}


===== Overall ATT (group aggregated) =====

-- Adaptation --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
     ATT    Std. Error     [ 95%  Conf. Int.] 
 -0.0073        0.0097    -0.0263      0.0117 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band]  
  2001   0.0558     0.0523       -0.0921      0.2037  
  2002   0.0106     0.0556       -0.1466      0.1679  
  2003  -0.0023     0.0369       -0.1068      0.1022  
  2004  -0.1668     0.0741       -0.3765      0.0428  
  2005  -0.0936     0.0257       -0.1665     -0.0208 *
  2006   0.0270     0.0527       -0.1220      0.1760  
  2007   0.0105     0.0832       -0.2248      0.2458  
  2008  -0.0836     0.0926       -0.3456      0.1784  
  2009  -0.0440     0.0369       -0.1484      0.0604  
  2010  -0.0942     0.0366       -0.1977      0.0093  
  2011   0.0195     0.0375       -0.0866      0.1256  
  2012   0.0088     0.0209       -0.0504      0.0680  
  2013   0.0229     0.0694       -0.1733      0.2191  
  2014   0.0307     0.0225       -0.0328      0.0942  
  2015   0.0289     0.0267       -0.0467      0.1045  
  2016  -0.0031     0.0236       -0.0698      0.0636  
  2017   0.0056     0.0182       -0.0457      0.0570  
  2018   0.0007     0.0131       -0.0364      0.0378  
  2019  -0.0169     0.0187       -0.0697      0.0359  
  2020  -0.0684     0.0183       -0.1203     -0.0165 *
  2021   0.0367     0.0148       -0.0051      0.0784  
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 

-- Mitigation --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
     ATT    Std. Error     [ 95%  Conf. Int.] 
 -0.0038        0.0152    -0.0337      0.0261 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band]  
  2001  -0.0832     0.1010       -0.3705      0.2041  
  2002   0.1660     0.0441        0.0406      0.2913 *
  2003   0.2063     0.0523        0.0577      0.3548 *
  2004  -0.0127     0.0886       -0.2645      0.2391  
  2005  -0.0289     0.0737       -0.2383      0.1806  
  2006   0.0500     0.0853       -0.1926      0.2926  
  2007  -0.0074     0.0826       -0.2423      0.2275  
  2008   0.0817     0.0732       -0.1265      0.2899  
  2009  -0.0872     0.0371       -0.1927      0.0184  
  2010   0.0615     0.0548       -0.0942      0.2173  
  2011  -0.0581     0.0353       -0.1584      0.0422  
  2012  -0.0347     0.0311       -0.1232      0.0537  
  2013  -0.0367     0.0305       -0.1233      0.0500  
  2014  -0.0402     0.0261       -0.1145      0.0341  
  2015   0.0604     0.0339       -0.0361      0.1569  
  2016  -0.0098     0.0236       -0.0770      0.0574  
  2017  -0.0184     0.0260       -0.0923      0.0556  
  2018  -0.0198     0.0328       -0.1131      0.0735  
  2019  -0.0384     0.0241       -0.1070      0.0302  
  2020   0.0141     0.0282       -0.0660      0.0943  
  2021  -0.0180     0.0322       -0.1097      0.0736  
  2022   0.0636     0.0061        0.0464      0.0808 *
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 

-- All climate --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
     ATT    Std. Error     [ 95%  Conf. Int.] 
 -0.0912        0.1095    -0.3059      0.1235 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band]  
  2001  -0.0268     0.0619       -0.3108      0.2572  
  2002   0.1012     0.0630       -0.1880      0.3903  
  2003   0.0136     0.0578       -0.2516      0.2789  
  2004  -0.1507     0.0715       -0.4788      0.1773  
  2005  -0.0973     0.0576       -0.3618      0.1671  
  2006  -0.0891     0.0618       -0.3727      0.1945  
  2007  -0.1796     0.0628       -0.4679      0.1086  
  2008  -0.1050     0.0669       -0.4120      0.2020  
  2009  -0.0923     0.0667       -0.3983      0.2137  
  2010  -0.0563     0.0610       -0.3362      0.2235  
  2011  -0.0904     0.0510       -0.3244      0.1436  
  2012  -0.0858     0.0462       -0.2978      0.1262  
  2013  -0.0979     0.0789       -0.4600      0.2642  
  2014  -0.1221     0.0660       -0.4252      0.1809  
  2015  -0.0533     0.0679       -0.3648      0.2582  
  2016  -0.0761     0.0878       -0.4790      0.3268  
  2017  -0.0908     0.1163       -0.6243      0.4426  
  2018  -0.0791     0.0773       -0.4338      0.2755  
  2019  -0.1677     0.0311       -0.3104     -0.0250 *
  2020  -0.1801     0.1782       -0.9978      0.6375  
  2021  -0.1614     0.0411       -0.3498      0.0271  
  2022   0.0188     0.0116       -0.0345      0.0721  
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 

-- Non-climate --
 
Call:
did::aggte(MP = att, type = "group")

Reference: Callaway, Brantly and Pedro H.C. Sant'Anna.  "Difference-in-Differences with Multiple Time Periods." Journal of Econometrics, Vol. 225, No. 2, pp. 200-230, 2021. <https://doi.org/10.1016/j.jeconom.2020.12.001>, <https://arxiv.org/abs/1803.09015> 


Overall summary of ATT's based on group/cohort aggregation:  
    ATT    Std. Error     [ 95%  Conf. Int.] 
 0.0119        0.0113    -0.0103      0.0341 


Group Effects:
 Group Estimate Std. Error [95% Simult.  Conf. Band]  
  2001   0.0012     0.0187       -0.0522      0.0546  
  2002   0.0182     0.0188       -0.0357      0.0720  
  2003   0.0195     0.0233       -0.0470      0.0860  
  2004   0.0126     0.0148       -0.0297      0.0549  
  2005  -0.0623     0.0198       -0.1188     -0.0058 *
  2006   0.0824     0.0176        0.0320      0.1328 *
  2007  -0.0478     0.0199       -0.1047      0.0091  
  2008   0.0541     0.0190       -0.0002      0.1083  
  2009  -0.0283     0.0223       -0.0921      0.0356  
  2010   0.0188     0.0202       -0.0390      0.0766  
  2011   0.0004     0.0276       -0.0785      0.0792  
  2012   0.0043     0.0214       -0.0568      0.0653  
  2013   0.0194     0.0200       -0.0379      0.0767  
  2014  -0.0024     0.0219       -0.0649      0.0602  
  2015   0.0081     0.0201       -0.0493      0.0655  
  2016   0.0090     0.0165       -0.0383      0.0563  
  2017   0.0262     0.0204       -0.0321      0.0845  
  2018   0.0315     0.0304       -0.0555      0.1185  
  2019  -0.0186     0.0180       -0.0701      0.0329  
  2020  -0.0223     0.0187       -0.0759      0.0313  
  2021  -0.0165     0.0353       -0.1175      0.0845  
  2022   0.0459     0.0153        0.0022      0.0896 *
---
Signif. codes: `*' confidence band does not cover 0

Control Group:  Not Yet Treated,  Anticipation Periods:  0
Estimation Method:  Doubly Robust
NULL 
Show code
summ_all_china <- dplyr::bind_rows(
  summ_line_overall(res_adapt), summ_line_overall(res_mitig),
  summ_line_overall(res_clim),  summ_line_overall(res_noncl)
) |>
  dplyr::mutate(
    pct = bt(att),
    lo  = bt(att, se)["lo"], hi = bt(att, se)["hi"]
  )

gt::gt(summ_all_china) |>
  gt::fmt_number(columns = c(pct, lo, hi), decimals = 1) |>
  gt::cols_label(pct="ATT (%)", lo="95% lo", hi="95% hi") |>
  gt::tab_caption("Overall ATT (group aggregated), back-transformed to %.")
Overall ATT (group aggregated), back-transformed to %.
label att se ATT (%) 95% lo 95% hi
All climate -0.08876721 0.06542946 −8.5 NA NA
Non-climate 0.01403241 0.01119864 1.4 NA NA

5.3 Intensity Adapt excluding China

Show code
# Run all four families
res_adapt      <- run_postdose_csdid_safe(bp_adapt[!grepl("CHN", adm2_id), ],      "Adaptation",  yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1:  34822   1514      1514     4
              post_bin n_adm2 n_treated
                <fctr>  <int>     <int>
1:     [18.5,1.39e+05]    380       380
2: (1.39e+05,8.39e+05]    374       374
3: (8.39e+05,3.25e+06]    379       379
4: (3.25e+06,6.35e+08]    381       381
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 1 units that were already treated in the first period.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2001,2002,2003,2006,2008,2009,2021.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2021 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2001,2002,2003,2005,2006,2007,2008,2009.
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 28 units that were already treated in the first period.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2002,2004,2006,2007,2008,2009.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2019
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2019 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2020 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 11 units that were already treated in the first period.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2004,2008,2009,2020.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2019
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2019 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2020 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix

Show code
res_mitig      <- run_postdose_csdid_safe(bp_mitig[!grepl("CHN", adm2_id), ],      "Mitigation",  yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1:  32430   1410      1410     4
              post_bin n_adm2 n_treated
                <fctr>  <int>     <int>
1:      [266,9.01e+04]    368       368
2: (9.01e+04,1.12e+06]    361       361
3: (1.12e+06,4.81e+06]    336       336
4: (4.81e+06,9.82e+08]    345       345
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2002,2007,2011.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2001,2002,2003,2004,2007,2009,2021.
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Simultaneous critical value is arguably `too large' to be realible. This
usually happens when number of observations per group is small and/or there is
no much variation in outcomes.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2004,2007,2020,2021.
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Simultaneous critical value is arguably `too large' to be realible. This
usually happens when number of observations per group is small and/or there is
no much variation in outcomes.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 7 units that were already treated in the first period.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2001,2003,2016,2019,2020.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2019
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2019 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2020 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix

Show code
res_climate    <- run_postdose_csdid_safe(bp_climate[!grepl("CHN", adm2_id), ],    "All climate", yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1:  92598   4026      4026     4
             post_bin n_adm2 n_treated
               <fctr>  <int>     <int>
1:    [18.5,1.18e+05]   1043      1043
2: (1.18e+05,9.2e+05]   1043      1043
3: (9.2e+05,4.71e+06]   1017      1017
4: (4.71e+06,2.3e+09]    923       923
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2001,2002,2003,2004.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 8 units that were already treated in the first period.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2021 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 35 units that were already treated in the first period.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2021 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 25 units that were already treated in the first period.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2019
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2019 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2021 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix

Show code
res_nonclimate <- run_postdose_csdid_safe(bp_nonclimate[!grepl("CHN", adm2_id), ], "Non-climate", yvar)
   n_rows n_adm2 n_treated  bins
    <int>  <int>     <int> <int>
1: 259808  11296     11296     4
               post_bin n_adm2 n_treated
                 <fctr>  <int>     <int>
1: [-1.24e+03,9.21e+05]   2888      2888
2:  (9.21e+05,4.11e+06]   2886      2886
3:  (4.11e+06,1.73e+07]   2829      2829
4:  (1.73e+07,7.57e+09]   2693      2693
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 98 units that were already treated in the first period.
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2021 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 210 units that were already treated in the first period.
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2021 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2021 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2021 in time
period 2021
Warning in compute.att_gt(dp): Not enough control units for group 2021 in time
period 2021 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 407 units that were already treated in the first period.
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2019
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2019 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2020 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, :
Dropped 764 units that were already treated in the first period.
Warning in pre_process_did(yname = yname, tname = tname, idname = idname, : Be aware that there are some small groups in your dataset.
  Check groups: 2017,2018,2019,2020.
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2001 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2001 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2002 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2002 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2003 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2003 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2004 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2004 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2005 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2005 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2006 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2006 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2007 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2007 in time
period 2020 to run specified regression
Warning: glm.fit: algorithm did not converge
Warning in compute.att_gt(dp): overlap condition violated for 2008 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2008 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2009 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2009 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2010 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2010 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2011 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2011 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2012 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2012 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2013 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2013 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2014 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2014 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2015 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2015 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2016 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2016 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2017 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2017 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2018 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2018 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2019 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2019 in time
period 2020 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2019
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2019 to run specified regression
Warning in compute.att_gt(dp): overlap condition violated for 2020 in time
period 2020
Warning in compute.att_gt(dp): Not enough control units for group 2020 in time
period 2020 to run specified regression
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Not returning pre-test Wald statistic due to singular covariance matrix
Warning in did::att_gt(yname = yvar, tname = "year", idname = "adm2_id_int", :
Simultaneous critical value is arguably `too large' to be realible. This
usually happens when number of observations per group is small and/or there is
no much variation in outcomes.

Show code
# Build a descriptive-sample panel using "All climate" adoption (change if desired)
descP <- merge(
  base_panel[, .(adm2_id, year, pollution_CO2, pollution_CO2_log)],
  adopt_climate, by = "adm2_id", all.x = TRUE
)
descP[, treated := as.integer(!is.na(g) & year >= g)]
descP[, ever_treated := as.integer(!is.na(g))]

# Helper: nice quantile summary
q_summ <- function(x) {
  c(N = sum(!is.na(x)),
    mean = mean(x, na.rm = TRUE),
    sd   = sd(x, na.rm = TRUE),
    p10  = quantile(x, .10, na.rm = TRUE),
    p50  = quantile(x, .50, na.rm = TRUE),
    p90  = quantile(x, .90, na.rm = TRUE))
}

5.3.1 Sample overview (counts, years, treated share)

Show code
library(data.table)

ov <- list(
  N_obs            = nrow(descP),
  N_ids            = uniqueN(descP$adm2_id),
  N_years          = uniqueN(descP$year),
  year_min_max     = paste(range(descP$year, na.rm = TRUE), collapse = "–"),
  N_ever_treated   = descP[, uniqueN(adm2_id[ever_treated == 1])],
  N_never_treated  = descP[, uniqueN(adm2_id[ever_treated == 0 | is.na(ever_treated)])],
  share_treated_by_2023 = with(descP[year == max(year, na.rm = TRUE)],
                               mean(ever_treated == 1, na.rm = TRUE))
)
as.data.table(ov)

5.3.2 Outcome summaries (overall & by ever-treated)

Show code
summ_all  <- q_summ(descP$pollution_CO2_log)
by_status <- descP[, as.list(q_summ(pollution_CO2_log)), by = ever_treated]

as.data.table(t(summ_all))[]
Show code
by_status[]

5.3.3 Adoption timing (cohort sizes, cumulative share)

Show code
library(ggplot2)

# Cohort histogram (first g per ADM2)
cohort_sizes <- adopt_climate[!is.na(g), .N, by = g][order(g)]
cohort_sizes%>%
  filter(g>=2000)%>%
ggplot(aes(g, N)) +
  geom_col() +
  labs(title = "Cohort size by first treatment year (All climate)",
       x = "First project year (g)", y = "ADM2 count") +
  theme_classic(base_size = 12)

Show code
# Cumulative treated share over time
# Cumulative treated share = fraction of ADM2 whose g <= year
share_treated <- descP[!is.na(g),
  .(share = mean(g <= year)), 
  by = year
]

# Also include never-treated in denominator
all_ids <- unique(descP$adm2_id)
total_n <- length(all_ids)

share_treated <- descP[, .(share = mean(!is.na(g) & g <= year)), by = year]

ggplot(share_treated, aes(year, share)) +
  geom_line() + geom_point() +
  scale_y_continuous(labels = scales::percent) +
  labs(title = "Share of ADM2 ever treated (cumulative)",
       x = NULL, y = NULL) +
  theme_classic(base_size = 12)

5.3.5 Raw event-time mean (not causal; descriptive)

Show code
descP[, rel_time := ifelse(is.na(g), NA_integer_, year - g)]
raw_es <- descP[!is.na(rel_time),
                .(y = mean(pollution_CO2_log, na.rm = TRUE)), by = rel_time]

ggplot(raw_es, aes(rel_time, y)) +
  geom_line() + geom_point() +
  geom_vline(xintercept = -1, linetype = 2) +
  labs(title = "Raw event-time mean: log(1+CO₂) (All climate)",
       x = "Event time (t - g)", y = "Mean log(1+CO₂)") +
  theme_classic(base_size = 12)

5.3.6 Top emitters (ADM2) — average over the sample window

Show code
# Extract ISO3 from GADM code pattern like "CHN.10.9_1"
descP[, iso3 := sub("\\..*$", "", adm2_id)]
top_adm2 <- descP[, .(avg_CO2 = mean(pollution_CO2, na.rm = TRUE)),
                  by = .(iso3, adm2_id)][order(-avg_CO2)][1:20]

top_adm2[]

6 Choropleth map of total post-treatment amounts per ADM2

Show code
library(sf)
library(ggplot2)
library(scales)

adm2$adm2_id <- adm2$GID_2

map_df <- adm2 |>
  merge(bp_adapt[, .(post_total = max(post_total, na.rm = TRUE)), by = adm2_id],
        by = "adm2_id", all.x = TRUE)

world_bg <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf") |>
  st_transform(st_crs(map_df))   # make sure CRS matches your ADM2 layer

ggplot() +
  # Grey background countries
  geom_sf(data = world_bg, fill = "grey90", color = "white", size = 0.1) +

  # Your ADM2 layer
  geom_sf(data = map_df, aes(fill = post_total), color = NA) +  
  scale_fill_viridis_c(
    option = "C",
    trans = "log",
    labels = label_number(scale_cut = cut_si("unit")),
    na.value = "grey90",
    name = "Total\n(Climate Finance)"
  ) +
  labs(
    title = "Where is post-treatment Climate finance concentrated?",
    subtitle = "ADM2-level total amounts, log scale. Light grey = no projects.",
    caption = "Source: GODAD; Author's calculations."
  ) +
  theme_minimal(base_size = 11) +
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    legend.position = "right",
    plot.title = element_text(face = "bold"),
    plot.subtitle = element_text(size = 9)
  )

Total post-treatment adaptation amounts by ADM2

Total post-treatment adaptation amounts by ADM2

7 Waffle chart: Share of total amount by bin

Show code
library(waffle)
library(dplyr)
library(stringr)
library(RColorBrewer)

# 1️⃣ Aggregate total amounts by dose bin
bin_amounts <- bp_adapt[!is.na(post_bin),
                        .(total_amt = sum(dose_amt, na.rm = TRUE)), 
                        by = post_bin] %>%
  mutate(post_bin = as.character(post_bin))

# 2️⃣ Extract numeric lower bound from bin labels for ordering
get_lower <- function(x) {
  as.numeric(str_extract(x, "[-+]?[0-9]*\\.?[0-9]+(?:e[+-]?\\d+)?"))
}

bin_amounts <- bin_amounts %>%
  mutate(lower_bound = get_lower(post_bin)) %>%
  arrange(lower_bound)

# 3️⃣ Convert to millions and build named vector in the **sorted order**
parts <- round(bin_amounts$total_amt / 1e7)  # 1 square = 10M
names(parts) <- bin_amounts$post_bin

# 4️⃣ Define number of bins explicitly
n_bins <- length(parts)

# 5️⃣ Pick a nice palette with the right length
# Paired works well up to 12; or use viridis(n_bins)
pal <- brewer.pal(n_bins, "Paired")   # or "PuBuGn", "YlOrRd", "Set2"...

bin_levels <- names(parts)  # order from lowest to highest bin

waffle_df <- tibble(
  part = factor(rep(bin_levels, times = parts), levels = bin_levels)
) %>%
  mutate(
    index = row_number(),
    y = (index - 1) %/% 20,   # number of rows
    x = (index - 1) %% 20
  )

# Reverse y so origin is bottom-left
waffle_df$y <- max(waffle_df$y) - waffle_df$y

# --- Plot ---
ggplot(waffle_df, aes(x, y, fill = part)) +
  geom_tile(color = "white", size = 0.25) +
  coord_equal() +
  scale_fill_manual(values = pal, name = "Dose bin") +
  labs(
    title = "Share of total adaptation amount by dose bin",
    subtitle = "Each square represents approximately 10 million USD.\nColors represent bins of post-treatment finance intensity (lower → higher).",
    x = NULL, y = NULL,
    caption = "Source: GODAD; Author's calculations."
  ) +
  theme_minimal(base_size = 12) +
  theme(
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right",
    plot.title = element_text(face = "bold"),
    plot.subtitle = element_text(size = 10),
    plot.caption = element_text(size = 8, hjust = 0)
  )

Share of total adaptation amount by dose bin (1 square = ~1M)

Share of total adaptation amount by dose bin (1 square = ~1M)
Show code
library(data.table)
setDT(godad)

# --- Aggregate by country-year ---
country_year_totals <- godad[, .(
  adapt_total       = sum(comm_loc_evensplit[is_adaptation], na.rm = TRUE),
  mitig_total       = sum(comm_loc_evensplit[is_mitigation], na.rm = TRUE),
  climate_total     = sum(comm_loc_evensplit[is_climate],    na.rm = TRUE),
  nonclimate_total  = sum(comm_loc_evensplit[is_nonclimate], na.rm = TRUE)
), by = .(gid_0, year)]


# --- Quick check ---
country_year_totals[order(-adapt_total)][1:10]

8 Lineplots / Ridgeplots of country trajectories

Show code
library(ggridges)
ggplot(country_year_totals, aes(x = log1p(nonclimate_total), y = factor(year))) +
  geom_density_ridges(scale = 3, rel_min_height = 0.01) +
  labs(x = "Log Adaptation Finance", y = "Year")

9 Bump Chart

Show code
library(ggbump)

# build ranks per year
ranked <- country_year_totals %>%
  mutate(year = as.integer(year)) %>%
  group_by(year) %>%
  mutate(rank_y = min_rank(desc(adapt_total))) %>%
  ungroup()

# take top 10 each year
top10 <- ranked %>%
  filter(rank_y <= 10)

# those with at least 2 years in top10 (for smooth bumps)
lines_df <- top10 %>%
  group_by(gid_0) %>%
  filter(n() >= 2) %>%
  ungroup()

ggplot(lines_df, aes(x = year, y = rank_y, color = gid_0, group = gid_0)) +
  geom_bump(size = 1.2) +
  geom_point(size = 2) +
  scale_y_reverse(breaks = 1:10) +
  labs(
    title = "Top 10 adaptation finance recipients over time",
    x = NULL, y = "Rank",
    color = "Country"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold"),
    legend.position = "right"
  )

Show code
library(dplyr)
library(tidyr)
library(ggplot2)
library(ggbump)

# rank each year
ranked <- country_year_totals %>%
  filter(year %in% 1995:2023)%>%
  mutate(year = as.integer(year)) %>%
  group_by(year) %>%
  mutate(rank_y = min_rank(desc(adapt_total))) %>%
  ungroup()

# contenders = countries that appear in top10 at least 3 years
contenders <- ranked %>%
  filter(rank_y <= 10) %>%
  count(gid_0, name = "n_top10") %>%
  filter(n_top10 >= 3) %>%
  pull(gid_0)

# build continuous panel for contenders (fill missing years with 0)
years_all <- sort(unique(ranked$year))
panel <- country_year_totals %>%
    filter(year %in% 1995:2023)%>%
  filter(gid_0 %in% contenders) %>%
  select(gid_0, year, adapt_total) %>%
  complete(gid_0, year = years_all, fill = list(adapt_total = 0)) %>%
  group_by(year) %>%
  mutate(rank_c = min_rank(desc(adapt_total))) %>%  # rank among contenders
  ungroup()

ggplot(panel, aes(year, rank_c, color = gid_0, group = gid_0)) +
  geom_bump(size = 1.2) +
  geom_point(size = 1.8) +
  scale_y_reverse(breaks = 1:10) +
  labs(title = "Top adaptation finance recipients over time (contenders)",
       x = NULL, y = "Rank") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "none",
        plot.title = element_text(face = "bold"))

10 Heatmaps (country × year matrix)

Show code
library(forcats)
country_year_heat <- country_year_totals %>%
  mutate(country = fct_reorder(gid_0, adapt_total, .fun = max, .desc = TRUE))

ggplot(country_year_heat, aes(x = year, y = country, fill = log1p(adapt_total))) +
  geom_tile() +
  scale_fill_viridis_c() +
  labs(fill = "Log Adaptation\nFinance")